package SQL_L

import org.apache.spark.sql.SparkSession
import org.junit.Test

class ColumnTest {
  //创建SparkSession
  val spark = SparkSession.builder()
    .master("local[6]")
    .appName("transformation")
    .getOrCreate()
  //隐式转换

  import spark.implicits._
  //应用函数
  import org.apache.spark.sql.functions._

  @Test
  def creation() = {
    val ds = Seq(Person("zhangsan", 15), Person("lisi", 10)).toDS()
    val ds1 = Seq(Person("zhangsan", 15), Person("lisi", 10)).toDS()


    /**
     * 1.
     * 使用 ' 创建列
     * 在使用 ' 创建前必须导入spark的隐式转换
     */
    val column = 'name
    /**
     * 2.
     * 使用 $ 创建
     * 使用 $ 创建前也需要导入spark的隐式转换
     */
    val column1 = $"name"
    /**
     * 3.
     * 使用col 创建
     * 使用前必须导入functions
     */
    val column2 = col("name")

    /**
     * 4.
     * 使用 column创建
     * 使用前必须导入functions
     */
    val column3 = column("name")

    //上述四种创建方式，没有关联的dataset
    ds.select(column).show()
    /**
     * 5.
     * 使用dataset.col创建
     * 会绑定，在逻辑计划中有不同的表现
     */
    val column4 = ds.col("name")
    val column5 = ds1.col("name")
    //为什么需要和dataset进行绑定呢？
    //在表的连接的时候需要
    ds.join(ds1, column4 === column5)

    /**
     * 6.
     * 使用dataset.apply创建
     */
    val column6 = ds.apply("name")
  }

  /**
   * 定义别名
   */
  @Test
  def as() = {
    val ds = Seq(Person("zhangsan", 15), Person("lisi", 10)).toDS()
    ds.select('name as "new_name").show()
    ds.select('age.as[Long]).show()
  }

  /**
   * 列的操作
   */
  @Test
  def api() = {
    val ds = Seq(Person("zhangsan", 25), Person("lisi", 15)).toDS()
    //需求一，ds 增加列，双倍年龄
    /**
     * 'age * 2实质上就是将一个表达式（逻辑计划表达式）附着到column对象上
     * 表达式在执行的时候对应每一条数据进行操作
     */
    ds.withColumn("doubleAge", 'age * 2).show()
    //需求二，模糊查询
    ds.where('name like "zhang%").show()
    //需求三，排序正反序
    ds.sort('age asc).show()
    //需求四，枚举判断
    ds.where('name isin("zhangsan", "wangwu")).show()
  }

}
